﻿using System;
using System.Collections.Generic;
using System.Linq;

using SharedGenomics.Core;

namespace SharedGenomics.Domain.Builders
{
    public class JobBuilder
    {
        //instances must be created through NewJob factory method
        protected JobBuilder(JobType jobType)
        {
            this.Type = jobType;
        }

        public static JobBuilder NewJob(JobType jobType)
        {
            switch (jobType)
            {
                case JobType.PModel:
                    return new PModelJobBuilder();
                case JobType.PCMH:
                    return new PCMHJobBuilder();
                case JobType.FastPepiBT:
                case JobType.PassocBT:
                case JobType.PassocQT:
                case JobType.PepiBT:
                case JobType.PepiQT:
                    return new JobBuilder(jobType);
                default:
                    throw new ArgumentException(String.Format("Invalid job type: {0}", jobType));
            }
        }

        public JobBuilder ForDataSet(int dataSetId)
        {
            this.DataSetId = dataSetId;
            return this;
        }

        public JobBuilder WithDescription(string description)
        {
            this.Description = description;
            return this;
        }

        public JobBuilder WithPermutations(short permutationCount)
        {
            this.PermutationCount = permutationCount;
            return this;
        }

        public JobBuilder ToAnalyse(string analysisVariable)
        {
            this.AnalysisVariable = analysisVariable;
            return this;
        }

        public JobBuilder WithOptions(ModelOptionFlags modelOptions)
        {
            this.PModelOptions = modelOptions;
            return this;
        }

        public JobBuilder StratifiedBy(string stratificationVariable)
        {
            this.StratificationVariable = stratificationVariable;
            return this;
        }

        public virtual JobInfo Build()
        {
            //data set id, analysis variable and permutation count must be set
            this.DataSetId.ThrowIfNull<BuilderStateException>(this.GetUnsetVariableExceptionMessage("Data Set Id"));
            this.AnalysisVariable.ThrowIfNull<BuilderStateException>(this.GetUnsetVariableExceptionMessage("Analysis variable"));

            this.PermutationCount.ThrowIfNull<BuilderStateException>(this.GetUnsetVariableExceptionMessage("Permutation count"));
            ExceptionHelper.ThrowIf<BuilderStateException>(this.PermutationCount.Value < 1, "Permutation count must be greater than zero");

            return new JobInfo
            {
                DataSetId = this.DataSetId.Value,
                AnalysisVariable = this.AnalysisVariable,
                PermutationCount = this.PermutationCount.Value,
                Description = this.Description,
                Type = this.Type
            };
        }

        protected string GetUnsetVariableExceptionMessage(string variable)
        {
            return string.Format("{0} must be set with builder before creation", variable ?? "<null>");
        }

        private JobType Type { get; set; }
        private int? DataSetId { get; set; }
        private string Description { get; set; }
        private short? PermutationCount { get; set; }
        private string AnalysisVariable { get; set; }
        protected ModelOptionFlags PModelOptions { get; private set; }
        protected string StratificationVariable { get; private set; }
    }
}
